home *** CD-ROM | disk | FTP | other *** search
- ;----------------------------------------------------------------------------
- ;File name: NET_TCON.SH Revision date: 1997.08.04
- ;Creator: Ulf Ronald Andersson Creation date: 1997.07.31
- ;(c)1997 by: Ulf Ronald Andersson All rights reserved
- ;----------------------------------------------------------------------------
- ;Required header declarations:
- ;
- ; .include "uran\STRUCT.SH"
- ; .include "uran\URAn_SYS.SH"
- ; .include "sting\TRANSPRT.SH"
- ; .include "sting\DOMAIN.SH"
- ; .include "sting\NET_TCON.SH"
- ;
- ;copy the above to the header of your program and 'uncomment' the includes
- ;----------------------------------------------------------------------------
- ;Purpose:
- ;
- ;The macros declared here will handle the translation of time and date values
- ;between three formats: The internal 2*16 bit code of TOS, the normal 32 bit
- ;network time format of internet, and the normal human format where each time
- ;unit is separate from the others.
- ;----------------------------------------------------------------------------
- ;NB: Having used any of these macros, you have to include a call like this:
- ;
- ; make TCON_links
- ;
- ; This must be somewhere in the executable code, after all 'tcon_' macros
- ; that are to be used in the program have been called at least once.
- ;----------------------------------------------------------------------------
- ;Available macros and their usage:
- ;
- ;
- ;tcon_real2tos The TOS time of a tcon struct is loaded from TOS realtime
- ;tcon_tos2real TOS realtime is loaded from the TOS time of a tcon struct
- ;tcon_man2tos Human time of a tcon struct is converted into its TOS time
- ;tcon_tos2man TOS time of a tcon struct is converted into its human time
- ;tcon_man2net Human time of a tcon struct is converted into network time
- ;tcon_net2man Network time of a tcon struct is converted into human time
- ;tcon_is_summer Flags summertime with -1 and non-summer with 0
- ;tcon_rd_zone Converts data from sting variable TIME_ZONE to zoneseconds
- ;tcon_rd_summer Converts data from sting variable TIME_SUMMER to tcon_summer
- ;
- ;All of these macros expect a pointer to a 'tcon' structure in a0 and they
- ;restore all CPU address and data registers to original values on exit.
- ;
- ; NB: use "ds.b sizeof_tcon" to reserve storage for a tcon structure.
- ;
- ;+NB: TIME_ZONE has a range of "-1440" to "+1440" in minutes ahead of GMT
- ; so for Germany or Sweden (for example) "+60" is correct.
- ; tcon_zoneseconds has a range of -86400 to +86400 in seconds, which
- ; corresponds to TIME_ZONE multiplied by 60
- ;----------------------------------------------------------------------------
- ;The tcon structure:
- ;
- struct tcon
- uint32 tcon_net_time ;network time from 00:00 Jan 1 1900 GMT
- int32 tcon_zoneseconds ;max +/- 45000 (== 12.5 hours)
- uint16 tcon_tos_date ;bitpacked date of Atari TOS
- uint16 tcon_tos_time ;bitpacked time of Atari TOS
- uint16 tcon_man_year ;human year
- uint16 tcon_man_month ;human month
- uint16 tcon_man_date ;human date
- uint16 tcon_man_hour ;human hour
- uint16 tcon_man_minute ;human minute
- uint16 tcon_man_second ;human second
- uint16 tcon_man_weekday ;human weekday
- d_alias tcon_summer ;sub_struct for daylight savings
- uint8 tcon_summer_start_month ;\
- uint8 tcon_summer_start_date ; \/ In this period another hour
- uint8 tcon_summer_end_month ; /\ is added to the zone time
- uint8 tcon_summer_end_date ;/ (Zero values disable this)
- d_end tcon
- ;
- ;NB: weekday support is limited to the conversion tcon_net2man.
- ; For tos and human formats that need weekday updated, you must
- ; first convert to network format, and then to human format.
- ; This is not needed unless weekday is necessary.
- ;
- ; examples of conversions making tcon_weekday valid:
- ;
- ; network format => tcon_net2man
- ; human format => tcon_man2net + tcon_net2man
- ; tos format => tcon_tos2man + tcon_man2net + tcon_net2man
- ;
- ;----------------------------------------------------------------------------
- ;
- NET_JAN_1980 equ 2524521600 ;1980.01.01 was a tuesday :-)
- NET_DAY equ 86400
- ;
- ;----------------------------------------------------------------------------
- ;
- .MACRO TCON_links
- _unidef tcon_real2tos
- _unidef tcon_tos2real
- _unidef tcon_man2tos
- _unidef tcon_tos2man
- _unidef tcon_man2net
- _unidef tcon_net2man
- _unidef tcon_rd_zone
- _unidef tcon_rd_summer
- _unidef tcon_is_summer
- .ENDM TCON_links
- ;
- _unidec tcon_real2tos
- _unidec tcon_tos2real
- _unidec tcon_man2tos
- _unidec tcon_tos2man
- _unidec tcon_man2net
- _unidec tcon_net2man
- _unidec tcon_rd_zone
- _unidec tcon_rd_summer
- _unidec tcon_is_summer
- ;
- ;-------------------------------------
- ;
- .MACRO tcon_real2tos
- _uniref tcon_real2tos
- jsr code_tcon_real2tos
- .ENDM tcon_real2tos
- ;
- .MACRO code_tcon_real2tos
- movem.l d0-d4/a0-a3,-(sp)
- move.l a0,a3 ;a3 -> tcon structure
- gemdos Tgetdate
- move d0,d3
- gemdos Tgettime
- move d0,d4
- gemdos Tgetdate
- cmp d0,d3
- beq.s .have_time
- move d0,d3
- gemdos Tgettime
- move d0,d4
- .have_time:
- move d3,tcon_tos_date(a3)
- move d4,tcon_tos_time(a3)
- movem.l (sp)+,d0-d4/a0-a3
- rts
- .ENDM code_tcon_real2tos
- ;
- ;-------------------------------------
- ;
- .MACRO tcon_tos2real
- _uniref tcon_tos2real
- jsr code_tcon_tos2real
- .ENDM tcon_tos2real
- ;
- .MACRO code_tcon_tos2real
- movem.l d0-d2/a0-a3,-(sp)
- move.l a0,a3 ;a3 -> tcon structure
- gemdos Tsettime,tcon_tos_time(a3)
- gemdos Tsetdate,tcon_tos_date(a3)
- movem.l (sp)+,d0-d2/a0-a3
- rts
- .ENDM code_tcon_tos2real
- ;
- ;-------------------------------------
- ;
- .MACRO tcon_tos2man
- _uniref tcon_tos2man
- jsr code_tcon_tos2man
- .ENDM tcon_tos2man
- ;
- .MACRO code_tcon_tos2man
- ;Sub converts TOS time to human time
- movem.l d0/d1,-(sp)
- move tcon_tos_date(a0),d0
- move d0,d1
- and #1<<5-1,d1
- move d1,tcon_man_date(a0)
- lsr #5,d0
- move d0,d1
- and #1<<4-1,d1
- move d1,tcon_man_month(a0)
- lsr #4,d0
- add #1980,d0
- move d0,tcon_man_year(a0)
- ;
- move tcon_tos_time(a0),d0
- move d0,d1
- and #1<<5-1,d1
- add d1,d1
- move d1,tcon_man_second(a0)
- lsr #5,d0
- move d0,d1
- and #1<<6-1,d1
- move d1,tcon_man_minute(a0)
- lsr #6,d0
- move d0,tcon_man_hour(a0)
- movem.l (sp)+,d0/d1
- rts
- .ENDM code_tcon_tos2man
- ;
- ;-------------------------------------
- ;
- .MACRO tcon_man2tos
- _uniref tcon_man2tos
- jsr code_tcon_man2tos
- .ENDM tcon_man2tos
- ;
- .MACRO code_tcon_man2tos
- ;Sub converts human time to TOS time
- movem.l d0/d1,-(sp)
- move tcon_man_year(a0),d1
- sub #1980,d1
- asl #4,d1
- move tcon_man_month(a0),d0
- and #1<<4-1,d0
- or d0,d1
- asl #5,d1
- move tcon_man_date(a0),d0
- and #1<<5-1,d0
- or d0,d1
- move d1,tcon_tos_date(a0)
- ;
- move tcon_man_hour(a0),d1
- asl #6,d1
- move tcon_man_minute(a0),d0
- and #1<<6-1,d0
- or d0,d1
- asl #5,d1
- move tcon_man_second(a0),d0
- lsr #1,d0
- and #1<<5-1,d0
- or d0,d1
- move d1,tcon_tos_time(a0)
- movem.l (sp)+,d0/d1
- rts
- .ENDM code_tcon_man2tos
- ;
- ;-------------------------------------
- ;
- .MACRO tcon_net2man
- _uniref tcon_net2man
- jsr code_tcon_net2man
- .ENDM tcon_net2man
- ;
- .MACRO code_tcon_net2man
- ;Sub converts network time to local human time
- movem.l d0-d3,-(sp)
- clr.l d3 ;zero summer adjustment for first lap
- .adjust_loop:
- move.l tcon_net_time(a0),d0
- add.l tcon_zoneseconds(a0),d0
- add.l d3,d0 ;add summer adjustment (on second lap when used)
- sub.l #NET_JAN_1980,d0
- clr d1 ;prep for seconds mixing
- lsr.l #1,d0 ;prescale to avoid overflow in remainder
- roxr d1 ;d1 bit 15 = odd seconds bit
- divu #NET_DAY/2,d0
- move d0,d2 ;d2 = whole days from 00:00 tuesday Jan 1st 1980
- clr d0 ;prep to separate remainder
- swap d0
- divu #60/2,d0 ;d0.lo = minutes from midnight
- swap d0
- move.b d0,d1 ;d1 = all seconds bits rotated 1 step right
- clr d0 ;prep to separate hours & minutes
- swap d0
- divu #60,d0
- move d0,tcon_man_hour(a0)
- swap d0
- move d0,tcon_man_minute(a0)
- rol #1,d1
- move d1,tcon_man_second(a0) ;this completes time_of_day conversion
- ;
- clr.l d0
- move d2,d0 ;d0 = d2 = days from Jan 1st 1980
- divu #4*365+1,d0 ;olympic periods since 1980
- asl #2,d0 ;are precisely 4 years each (until 2100)
- move d0,d1 ;d1 = years that formed olympics
- clr d0 ;prep to separate leap year
- swap d0 ;d0 = remaining days in last olympic
- cmp #366,d0 ;first year in olympic is leap year
- bhs.s .more_years
- subq #1,d0 ;adjust index for post-leap_day (most common)
- cmp #58,d0 ;beyond February ?
- bgt.s .done_years ;then it is now normalized
- beq.s .leap_day ;leap day is treated separately
- addq #1,d0 ;restore original index for Jan 1..Feb 28
- bra.s .done_years ;then treat it as any other year
- ;
- .leap_day:
- move #365,d0 ;beyond the table for days in normal years
- bra.s .done_years
-
- ;
- .more_years:
- subq #1,d0 ;remove leap day from days in d0
- divu #365,d0 ;d0.lo = full years in last olympic
- add d0,d1 ;d1 = total years since 1980
- swap d0 ;d0 = day_in_year
- .done_years:
- add #1980,d1 ;d1 = real year
- move d1,tcon_man_year(a0)
- add d0,d0 ;prep to index 16 bit words
- move .day_table(pc,d0.w),d0 ;d0 = month<<8 + date
- clr d1
- move.b d0,d1
- lsr #8,d0
- move d0,tcon_man_month(a0)
- move d1,tcon_man_date(a0)
- tst d3 ;summer adjustment already done ?
- bne.s .finish_net2man
- move.l #3600,d3 ;prep to adjust by adding one hour
- tcon_is_summer
- bne .adjust_loop
- .finish_net2man:
- addq #2,d2 ;adjust weekday offset, so we get sunday=0
- divu #7,d2
- swap d2 ;d2 = weekday offset 0=sunday .. 6= saturday
- move d2,tcon_man_weekday(a0)
- movem.l (sp)+,d0-d3
- rts
- ;
- .day_table:
- dc.w $101,$102,$103,$104,$105,$106,$107,$108,$109,$10A ;January
- dc.w $10B,$10C,$10D,$10E,$10F,$110,$111,$112,$113,$114
- dc.w $115,$116,$117,$118,$119,$11A,$11B,$11C,$11D,$11E,$11F
- ;
- dc.w $201,$202,$203,$204,$205,$206,$207,$208,$209,$20A ;February
- dc.w $20B,$20C,$20D,$20E,$20F,$210,$211,$212,$213,$214
- dc.w $215,$216,$217,$218,$219,$21A,$21B,$21C
- ;
- dc.w $301,$302,$303,$304,$305,$306,$307,$308,$309,$30A ;March
- dc.w $30B,$30C,$30D,$30E,$30F,$310,$311,$312,$313,$314
- dc.w $315,$316,$317,$318,$319,$31A,$31B,$31C,$31D,$31E,$31F
- ;
- dc.w $401,$402,$403,$404,$405,$406,$407,$408,$409,$40A ;April
- dc.w $40B,$40C,$40D,$40E,$40F,$410,$411,$412,$413,$414
- dc.w $415,$416,$417,$418,$419,$41A,$41B,$41C,$41D,$41E
- ;
- dc.w $501,$502,$503,$504,$505,$506,$507,$508,$509,$50A ;May
- dc.w $50B,$50C,$50D,$50E,$50F,$510,$511,$512,$513,$514
- dc.w $515,$516,$517,$518,$519,$51A,$51B,$51C,$51D,$51E,$51F
- ;
- dc.w $601,$602,$603,$604,$605,$606,$607,$608,$609,$60A ;June
- dc.w $60B,$60C,$60D,$60E,$60F,$610,$611,$612,$613,$614
- dc.w $615,$616,$617,$618,$619,$61A,$61B,$61C,$61D,$61E
- ;
- dc.w $701,$702,$703,$704,$705,$706,$707,$708,$709,$70A ;July
- dc.w $70B,$70C,$70D,$70E,$70F,$710,$711,$712,$713,$714
- dc.w $715,$716,$717,$718,$719,$71A,$71B,$71C,$71D,$71E,$71F
- ;
- dc.w $801,$802,$803,$804,$805,$806,$807,$808,$809,$80A ;August
- dc.w $80B,$80C,$80D,$80E,$80F,$810,$811,$812,$813,$814
- dc.w $815,$816,$817,$818,$819,$81A,$81B,$81C,$81D,$81E,$81F
- ;
- dc.w $901,$902,$903,$904,$905,$906,$907,$908,$909,$90A ;September
- dc.w $90B,$90C,$90D,$90E,$90F,$910,$911,$912,$913,$914
- dc.w $915,$916,$917,$918,$919,$91A,$91B,$91C,$91D,$91E
- ;
- dc.w $A01,$A02,$A03,$A04,$A05,$A06,$A07,$A08,$A09,$A0A ;October
- dc.w $A0B,$A0C,$A0D,$A0E,$A0F,$A10,$A11,$A12,$A13,$A14
- dc.w $A15,$A16,$A17,$A18,$A19,$A1A,$A1B,$A1C,$A1D,$A1E,$A1F
- ;
- dc.w $B01,$B02,$B03,$B04,$B05,$B06,$B07,$B08,$B09,$B0A ;November
- dc.w $B0B,$B0C,$B0D,$B0E,$B0F,$B10,$B11,$B12,$B13,$B14
- dc.w $B15,$B16,$B17,$B18,$B19,$B1A,$B1B,$B1C,$B1D,$B1E
- ;
- dc.w $C01,$C02,$C03,$C04,$C05,$C06,$C07,$C08,$C09,$C0A ;December
- dc.w $C0B,$C0C,$C0D,$C0E,$C0F,$C10,$C11,$C12,$C13,$C14
- dc.w $C15,$C16,$C17,$C18,$C19,$C1A,$C1B,$C1C,$C1D,$C1E,$C1F
- ;
- dc.w $21D ;special entry for leap day
- .ENDM code_tcon_net2man
- ;
- ;-------------------------------------
- ;
- .MACRO tcon_man2net
- _uniref tcon_man2net
- jsr code_tcon_man2net
- .ENDM tcon_man2net
- ;
- .MACRO code_tcon_man2net
- ;Sub converts local human time to network time
- movem.l d0-d3,-(sp)
- tcon_is_summer
- move.l #3600,d3
- and d0,d3
- move tcon_man_year(a0),d0
- sub #1980,d0 ;make year relative to 1980
- move d0,d1
- lsr #2,d0 ;d0 = olympics
- mulu #365*4+1,d0 ;d0 = days of full olympics
- and #1<<2-1,d1 ;d1 = years of current olympic
- seq d2 ;d2.b=$FF if current year is leaping, else $00
- beq.s .done_years
- mulu #365,d1 ;d1 = normal days of full years of current olympic
- addq #1,d1 ;add a leap day for the first of them
- add d1,d0 ;d0 = days of all full years (NB: <65536 !!!)
- ;
- .done_years:
- and #12,d2 ;d2 = table offset for leap year, or zero
- add tcon_man_month(a0),d2 ;d2 = month index (0-23, with 12-23 for leap years)
- subq #1,d2 ;subtract one since months don't use zero
- add d2,d2 ;prep to index 16 bit words
- add .month_table(pc,d2.w),d0 ;add days before current month to d0
- add tcon_man_date(a0),d0 ;add date in current month to d0
- subq #1,d0 ;subtract one, since dates don't use zero
- mulu #NET_DAY/2,d0
- add.l d0,d0 ;d0 = date in seconds relative to Jan 1 1980
- add.l #NET_JAN_1980,d0 ;d0.l = local date (but not yet time) in seconds
- move tcon_man_hour(a0),d1
- mulu #60,d1
- add tcon_man_minute(a0),d1
- mulu #60/2,d1 ;NB: the "/2" is needed to avoid overflow
- add.l d1,d1 ;This doubling compensates for the above "/2"
- clr.l d2
- move tcon_man_second(a0),d2
- add.l d2,d1 ;d1.l = local time_of_day in seconds
- add.l d1,d0 ;d0.l = local time in network format
- sub.l d3,d0 ;adjust for daylight savings
- sub.l tcon_zoneseconds(a0),d0 ;d0.l = true network time
- move.l d0,tcon_net_time(a0)
- movem.l (sp)+,d0-d3
- rts
- ;
- .month_table:
- dc.w 0,31,59,90,120,151,181,212,243,273,304,334
- dc.w 0,31,60,91,121,152,182,213,244,274,305,335
- .ENDM code_tcon_man2net
- ;
- ;-------------------------------------
- ;
- .MACRO tcon_is_summer
- _uniref tcon_is_summer
- jsr code_tcon_is_summer
- .ENDM tcon_is_summer
- ;
- .MACRO code_tcon_is_summer
- move.l d1,-(sp)
- tst.l tcon_summer(a0)
- beq.s .exit_false
- clr.l d0
- move tcon_man_month(a0),d0
- add #12,d0
- sub.b tcon_summer_start_month(a0),d0
- divu #12,d0
- swap d0
- tst d0 ;start month now ?
- bne.s .not_start_month
- ;start month is now
- move tcon_man_date(a0),d0
- cmp.b tcon_summer_start_date(a0),d0
- blo.s .exit_false
- .exit_true:
- move.l (sp)+,d1
- moveq #-1,d0
- rts
- ;
- .not_start_month:
- clr.l d1
- move.b tcon_summer_end_month(a0),d1
- add #12,d1
- sub.b tcon_summer_start_month(a0),d1
- divu #12,d1
- swap d1
- cmp d1,d0
- bhi.s .exit_false
- blo.s .exit_true
- ;end month is now
- move tcon_man_date(a0),d0
- cmp.b tcon_summer_end_date(a0),d0
- blo.s .exit_true
- .exit_false:
- move.l (sp)+,d1
- clr.l d0
- rts
- .ENDM code_tcon_is_summer
- ;
- ;-------------------------------------
- ;
- .MACRO tcon_rd_zone
- _uniref tcon_rd_zone
- jsr code_tcon_rd_zone
- .ENDM tcon_rd_zone
- ;
- .MACRO code_tcon_rd_zone
- ;Sub converts config variable TIME_ZONE to tcon_zoneseconds
- movem.l d0-d2/a0-a2,-(sp)
- move.l a0,-(sp)
- getvstr TIME_ZONE_vn_s(pc)
- is_unblank.i d0
- clr d1
- clr.l d2
- move.l a0,d0
- beq.s .have_zone
- move.b (a0)+,d1
- cmp.b #'+',d1
- beq.s .use_sign
- cmp.b #'-',d1
- beq.s .use_sign
- subq #1,a0
- .use_sign:
- clr d0
- .loop:
- move.b (a0)+,d0
- sub.b #'0',d0
- blt.s .have_zone
- cmp.b #9,d0
- bhi.s .have_zone
- mulu #10,d2
- add d0,d2
- cmp #1440,d2 ;too high ?
- bls.s .loop ;loop for legal values
- clr.l d2 ;force illegal value to zero
- .have_zone:
- mulu #60,d2 ;convert to seconds
- cmp.b #'-',d1
- bne.s .keep_sign
- neg.l d2 ;adjust to negative sign
- .keep_sign:
- move.l (sp)+,a0
- move.l d2,tcon_zoneseconds(a0)
- movem.l (sp)+,d0-d2/a0-a2
- rts
- ;
- TIME_ZONE_vn_s:
- dc.b 'TIME_ZONE',NUL
- even
- .ENDM code_tcon_rd_zone
- ;
- ;-------------------------------------
- ;
- .MACRO tcon_rd_summer
- _uniref tcon_rd_summer
- jsr code_tcon_rd_summer
- .ENDM tcon_rd_summer
- ;
- .MACRO code_tcon_rd_summer
- ;Sub converts config variable TIME_ZONE to tcon_zoneseconds
- movem.l d0-d2/a0-a2,-(sp)
- move.l a0,-(sp)
- getvstr TIME_SUMMER_vn_s(pc)
- is_unblank.i d0
- move.l a0,d0
- beq.s .have_summer
- diptobip (a0)
- .have_summer:
- move.l (sp)+,a0
- move.l d0,tcon_summer(a0)
- movem.l (sp)+,d0-d2/a0-a2
- rts
- ;
- TIME_SUMMER_vn_s:
- dc.b 'TIME_SUMMER',NUL
- even
- .ENDM code_tcon_rd_summer
- ;
- ;----------------------------------------------------------------------------
- ;End of file: NET_TCON.SH
- ;----------------------------------------------------------------------------
-